package com.template.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.ResourceUtils;
import org.springframework.web.servlet.config.annotation.*;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templatemode.TemplateMode;

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 配置 静态资源加载的路径
 * 跨域CORS配置
 * 某些请求不要拦截
 */
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
    private ApplicationContext applicationContext;

    /***
     * 可以从 jar 外部加载 静态文件
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        String staticPath = MessageFormat.format("{0}/static/", System.getProperty("user.dir"));
        File staticFile = new File(staticPath);
        if (staticFile.exists()) {
            //放置 ico
            registry.addResourceHandler("/static/**").addResourceLocations("file:" + staticPath);
        } else {
            registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/static/");

        }
        // 解决swagger无法访问
        registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        // 解决swagger的js文件无法访问
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    public void setApplicationContext(final ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }

    /***
     * 可以从jar外部加载 templates 模板
     * @return
     */
    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        String templatesPath = MessageFormat.format("{0}/templates/", System.getProperty("user.dir"));
        File templatesFile = new File(templatesPath);
        if (templatesFile.exists()) {
            templateResolver.setPrefix("file:" + templatesPath);
        } else {
            templateResolver.setPrefix(ResourceUtils.CLASSPATH_URL_PREFIX + "/templates/");
        }
        templateResolver.setSuffix(".html");

        templateResolver.setTemplateMode(TemplateMode.HTML);

        templateResolver.setCacheable(false);
        return templateResolver;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //1.需要先定義一個convert轉換信息對象
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        //2.添加fastJson配置信息，比如是否要格式化返回的json数据
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        //处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastJsonConverter.setSupportedMediaTypes(fastMediaTypes);
        //3.在convert中添加配置信息
        fastJsonConverter.setFastJsonConfig(fastJsonConfig);
        //4.将converter添加到converters中
        converters.add(fastJsonConverter);
    }

    /**
     * 跨域CORS设置
     *
     * @param registry
     */
    @Override
    //重写父类提供的跨域请求处理的接口
    public void addCorsMappings(CorsRegistry registry) {
        //添加映射路径
        registry.addMapping("/**")
                .allowedHeaders("*")
                //是否发送Cookie信息
                .allowCredentials(true)
                //放行哪些原始域(请求方式)
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                //放行哪些原始域
                .allowedOrigins("*")
                //放行哪些原始域(头部信息)
                .allowedHeaders("*");
    }

}
